package com.leyou.auth.service;

import com.leyou.auth.config.JwtProperties;
import com.leyou.common.auth.entity.Payload;
import com.leyou.common.auth.entity.UserInfo;
import com.leyou.common.auth.utils.JwtUtils;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exceptions.LyException;
import com.leyou.common.utils.CookieUtils;
import com.leyou.user.client.UserClient;
import com.leyou.user.dto.UserDTO;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @Auther: xiang
 * @Date: 2019/8/29 21:10
 * @Description:
 */
@Service
public class AuthServcie {
    @Autowired
    private JwtProperties prop;
    @Autowired
    private UserClient userClient;
    @Autowired
    private StringRedisTemplate redisTemplate;
    private static final String USER_ROLE = "role_user";

    public void login(String username, String password, HttpServletResponse response) {
        try {
            //查询用户是否存在
            UserDTO userDTO = userClient.queryUserByUsernameAndPassword(username, password);
            UserInfo userInfo = new UserInfo(userDTO.getId(), userDTO.getUsername(), USER_ROLE);
            //生产token
            String token = JwtUtils.generateTokenExpireInMinutes(userInfo, prop.getPrivateKey(), prop.getUser().getExpire());
            //写入token
            CookieUtils.newBuilder()
                    .response(response)//response用于手写cookie
                    .httpOnly(true)//保证安全防止SSS攻击,不允许js操作cookie
                    .domain(prop.getUser().getCookieDomain())//设置domain
            .name(prop.getUser().getCookieName())// cookie名字
             .value(token)//设置value值
                    .build();
        } catch (Exception e) {
           throw new  LyException(ExceptionEnum.INVALID_USERNAME_PASSWORD);
        }
    }

      public UserInfo verifyUser(HttpServletRequest request, HttpServletResponse response) {

          try {
              //读取cookie
              String token = CookieUtils.getCookieValue(request, prop.getUser().getCookieName());

              //获取token中的载荷
              Payload<UserInfo> payload = JwtUtils.getInfoFromToken(token, prop.getPublicKey(), UserInfo.class);
              // 获取token的id，校验黑名单
              String id = payload.getId();
              Boolean boo = redisTemplate.hasKey(id);
              if (boo != null && boo) {
                  // 抛出异常，证明token无效，直接返回401
                  throw new LyException(ExceptionEnum.UNAUTHORIZED);
              }
              //获得过期时间
              Date expiration = payload.getExpiration();
              //获得刷新的时间
              DateTime refreshTime = new DateTime(expiration.getTime())
                      .minusMinutes(prop.getUser().getMinRefreshInterval()); //减去分钟minusMinutes
              //判断当前时间是否到了刷新时间
              if (refreshTime.isBefore(System.currentTimeMillis())){
                  // 如果过了刷新时间，则生成新token
                  token = JwtUtils.generateTokenExpireInMinutes(payload.getUserInfo(), prop.getPrivateKey(), prop.getUser().getExpire());
                  // 写入cookie
                  CookieUtils.newBuilder()
                          // response,用于写cookie
                          .response(response)
                          // 保证安全防止XSS攻击，不允许JS操作cookie
                          .httpOnly(true)
                          // 设置domain
                          .domain(prop.getUser().getCookieDomain())
                          // 设置cookie名称和值
                          .name(prop.getUser().getCookieName()).value(token)
                          // 写cookie
                          .build();


              }
              return  payload.getUserInfo();
          } catch (Exception e) {
              throw new LyException(ExceptionEnum.UNAUTHORIZED);
          }
      }

    /**
     * 退出登陆
     * @param request
     * @param response
     */
    public void logout(HttpServletRequest request, HttpServletResponse response) {
        //获得cookie
        String token = CookieUtils.getCookieValue(request, prop.getUser().getCookieName());
        //获得载荷
        Payload<Object> payload = JwtUtils.getInfoFromToken(token, prop.getPublicKey());
        //获得tokenId 和过期时间
        String tokenId = payload.getId();
        long expireDate = payload.getExpiration().getTime()-System.currentTimeMillis();
        //存入redis,剩余时间超过五秒才写
        if(expireDate>5000){
            redisTemplate.opsForValue().set(tokenId,"", expireDate, TimeUnit.MILLISECONDS);

        }

        // 删除cookie
        CookieUtils.deleteCookie(prop.getUser().getCookieName(), prop.getUser().getCookieDomain(), response);

    }
}